#include "MapLoader.hpp"

/** 
* Loads binary map file.
*/
bool MapLoader::loadMap(string fileName, Map** map, RegionManager* regionManager){
    //Open file stream.
	ifstream fileStream;
	fileStream.open(fileName.c_str(), ios::in | ios::binary);
	if(fileStream.good()){
        //Get map name
		unsigned char mapNameLength = 0;
		fileStream.read((char*)&mapNameLength, sizeof mapNameLength);
		char* mapNameChr = new char[mapNameLength+1];
		fileStream.read(mapNameChr, mapNameLength);
		mapNameChr[mapNameLength] = '\0';
		string mapName = mapNameChr;
		delete mapNameChr;

        //Get map parameters.
		unsigned short width = 0;
		fileStream.read((char*)&width, sizeof width);
		unsigned short height = 0;
		fileStream.read((char*)&height, sizeof height);

		cout << "Map Name: '" << mapName << "', Size: " << width << "x" << height << endl;
		Map* loadMap = new Map(mapName, width, height);
		
        bool loadingRegions = false;
		unsigned short tile = 0;
		while(!fileStream.eof()){
            if(!loadingRegions){
                //Read tile number
                fileStream.read((char*) &tile, sizeof tile);

                //End of tiles delimiter
                if (tile == 0xFFFF) {
                    loadingRegions = true;
                    continue;
                }
                unsigned char tileInfo = 0;
                fileStream.read((char*) &tileInfo, sizeof tileInfo);
                //Check which tile info needs reading.
                if ((tileInfo & 2) != 0) {
                    unsigned short layer = 0;
                    fileStream.read((char*) &layer, sizeof layer);
                    loadMap->tiles[tile][0] = layer;
                } else {
                    loadMap->tiles[tile][0] = NO_SPRITE;
                }
                if ((tileInfo & 4) != 0) {
                    unsigned short layer = 0;
                    fileStream.read((char*) &layer, sizeof layer);
                    loadMap->tiles[tile][1] = layer;
                } else {
                    loadMap->tiles[tile][1] = NO_SPRITE;
                }
                if ((tileInfo & 8) != 0) {
                    unsigned short layer = 0;
                    fileStream.read((char*) &layer, sizeof layer);
                    loadMap->tiles[tile][2] = layer;
                } else {
                    loadMap->tiles[tile][2] = NO_SPRITE;
                }
                if ((tileInfo & 16) != 0) {
                    unsigned short layer = 0;
                    fileStream.read((char*) &layer, sizeof layer);
                    loadMap->tiles[tile][3] = layer;
                } else {
                    loadMap->tiles[tile][3] = NO_SPRITE;
                }
                if ((tileInfo & 32) != 0) {
                    unsigned short layer = 0;
                    fileStream.read((char*) &layer, sizeof layer);
                    loadMap->tiles[tile][4] = layer;
                } else {
                    loadMap->tiles[tile][4] = NO_SPRITE;
                }
                if ((tileInfo & 64) != 0) {
                    unsigned char properties = 0;
                    fileStream.read((char*) &properties, sizeof properties);
                    loadMap->tiles[tile].properties = properties;
                } else {
                    loadMap->tiles[tile].properties = 0;
                }
            }else{
                byte namelen = 0;
				//Load script name
				fileStream.read((char*)&namelen, sizeof(namelen));
				char script[OBJECT_SCRIPT_LENGTH];
				
				fileStream.read((char*)&script, namelen);
				script[namelen] = 0;
				Region* region = regionManager->createRegion(script);

				//Load region name.
                fileStream.read((char*)&namelen, sizeof(namelen));
                fileStream.read((char*)&region->name, namelen);
                region->name[namelen] = 0;
				
				//Load region size and position
                fileStream.read((char*)&region->x, sizeof(region->x));
                fileStream.read((char*)&region->y, sizeof(region->y));
                fileStream.read((char*)&region->width, sizeof(region->width));
                fileStream.read((char*)&region->height, sizeof(region->height));
            }
            fileStream.peek();
		}
		fileStream.close();
        *map = loadMap;
		return true;
	}else{
		cout << "Failed to read";
	}
	cout << "Done reading" << endl;
	return false;
}